{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "e99c9a4b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "\n",
       "try {\n",
       "require(['notebook/js/codecell'], function(codecell) {\n",
       "  codecell.CodeCell.options_default.highlight_modes[\n",
       "      'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n",
       "  Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
       "      Jupyter.notebook.get_cells().map(function(cell){\n",
       "          if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
       "  });\n",
       "});\n",
       "} catch (e) {};\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "\n",
       "try {\n",
       "require(['notebook/js/codecell'], function(codecell) {\n",
       "  codecell.CodeCell.options_default.highlight_modes[\n",
       "      'magic_text/x-csrc'] = {'reg':[/^%%pybind11/]};\n",
       "  Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
       "      Jupyter.notebook.get_cells().map(function(cell){\n",
       "          if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
       "  });\n",
       "});\n",
       "} catch (e) {};\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import sys\n",
    "import os\n",
    "import argparse\n",
    "import time\n",
    "import numpy as np\n",
    "import pynq\n",
    "from PIL import Image\n",
    "\n",
    "from AOS import *\n",
    "from IoU import *\n",
    "\n",
    "import cBBox\n",
    "import jpgLoader\n",
    "\n",
    "os.system(\"sudo sh -c \\\"sync && echo 3 > /proc/sys/vm/drop_caches\\\"\")\n",
    "\n",
    "def get_image_batch(IMG_DIR):\n",
    "\timage_list = [f for f in os.listdir(IMG_DIR) if f.endswith('.jpg')]\n",
    "\timage_list.sort(key= lambda x:int(x[:-4]))\n",
    "\tbatches = []\n",
    "\tfor i in range(0, len(image_list), BATCH_SIZE):\n",
    "\t\tpaths = []\n",
    "\t\tfor b in range(BATCH_SIZE):\n",
    "\t\t\tpaths.append(IMG_DIR + image_list[i:i+BATCH_SIZE][b])\n",
    "\t\tbatches.append(paths)\n",
    "\treturn batches\n",
    "\n",
    "def load_image(image_batchs):\n",
    "\timages = np.zeros((BATCH_SIZE,IMAGE_ROW*IMAGE_COL*3), dtype = np.uint8)\n",
    "\tfor i in range(BATCH_SIZE):\n",
    "\t\timage = np.array(Image.open(image_batchs[i]).resize((IMAGE_COL, IMAGE_ROW)).convert('RGB'))\n",
    "\t\timages[i] = image.flatten()\n",
    "\treturn images\n",
    "\n",
    "def load_image_to_ddr(image_batchs):\n",
    "\timage_list = []\n",
    "\tfor b in range(len(image_batchs)):\n",
    "\t\timage_list.append(load_image(image_batchs[b]))\n",
    "\treturn image_list"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aad99055",
   "metadata": {},
   "source": [
    "## load bitstream"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "c4a3bcab",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overlay loaded\n"
     ]
    }
   ],
   "source": [
    "bitfile = \"AOS-SkyNet.bit\"\n",
    "overlay = pynq.Overlay(bitfile)\n",
    "PulseGen = overlay.PulseGen\n",
    "TDM = overlay.OSM_Array\n",
    "dma = overlay.axi_dma\n",
    "print(\"Overlay loaded\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0c1b520d",
   "metadata": {},
   "source": [
    "## initialize image loader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "b5b8e61c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Allocating memory done\n",
      "load image to ddr done\n"
     ]
    }
   ],
   "source": [
    "BATCH_SIZE = 25\n",
    "IMAGE_ROW, IMAGE_COL = 360, 640\n",
    "N_THREAD = 8\n",
    "IMG_DIR = '../dac_sdc_2021/images/'\n",
    "\n",
    "result = np.zeros(shape=(1000 // BATCH_SIZE, BATCH_SIZE, 4), dtype=np.int32)\n",
    "out_cnt = -1\n",
    "ping, pong = 0, 1\n",
    "\n",
    "img = [None] * 2\n",
    "img[0] = pynq.allocate(shape=(BATCH_SIZE, IMAGE_ROW * IMAGE_COL * 3), dtype=np.uint8, cacheable=1)\n",
    "img[1] = pynq.allocate(shape=(BATCH_SIZE, IMAGE_ROW * IMAGE_COL * 3), dtype=np.uint8, cacheable=1)\n",
    "out = [None] * 2\n",
    "out[0] = pynq.allocate(shape=(BATCH_SIZE, 2, 7), dtype=np.int16, cacheable=1)\n",
    "out[1] = pynq.allocate(shape=(BATCH_SIZE, 2, 7), dtype=np.int16, cacheable=1)\n",
    "print(\"Allocating memory done\")\n",
    "\n",
    "image_batchs = get_image_batch(IMG_DIR)\n",
    "ground_truth_box = load_ground_truth('ground_truth.txt')\n",
    "image_list = load_image_to_ddr(image_batchs)\n",
    "print(\"load image to ddr done\")\n",
    "\n",
    "cboxer = cBBox.cBBox(BATCH_SIZE)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e277d5b",
   "metadata": {},
   "source": [
    "## config AOS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "19ed5c28",
   "metadata": {},
   "outputs": [],
   "source": [
    "vs = [700, 750, 800, 850]\n",
    "vi = 0\n",
    "os.system(\"sudo dvs \"+str(vs[vi]))\n",
    "path_index_sorted = [21, 16, 26, 7, 14, 24, 1, 22, 3, 19, 28, 0, 6, 2, 13, 9] # sorted critical path index\n",
    "cpi = path_index_sorted[13]\n",
    "\n",
    "T = 280\n",
    "path_cnt = 32\n",
    "MMF_V = 1\n",
    "MMF_H = 7\n",
    "repeat = MMF_V*7\n",
    "t_skew = [0.454,0.429,0.261,0.336,0.292,1.631,0.361,0.477,1.296,0.139,1.596,0.105,1.415,1.095,0.360,1.381,0.445,1.391,1.397,0.446,0.274,0.05,0.246,1.335,0.435,0.911,0.410,1.752,0.359,1.774,1.731,1.728]\n",
    "uv = [0.89, 0.83, 0.78, 0.74]\n",
    "t_ref = [2.530,2.542,2.345,2.470,0.000,0.000,2.458,2.631,0.000,1.708,0.000,0.000,0.000,2.000,2.542,0.000,2.661,0.000,0.000,2.542,0.000,2.310,2.405,0.000,2.548,0.000,2.589,0.000,2.470,0.000,0.000,0.000]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c21b3308",
   "metadata": {},
   "source": [
    "## run AOS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "f51d9811",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "interation 0 start\n",
      "interation 0 finish\n",
      "Average IoU: 0.7308197844604933\n",
      "Frequency 300MHz, theta 150.0, t_shadow 1.786ns, t_d 1.553ns, FPGA temperature 56.619°C\n",
      "interation 1 start\n",
      "interation 1 finish\n",
      "Average IoU: 0.686495058899663\n",
      "Frequency 310MHz, theta 158.5, t_shadow 1.826ns, t_d 1.594ns, FPGA temperature 58.010°C\n"
     ]
    }
   ],
   "source": [
    "f = 300\n",
    "iteration = 0\n",
    "for test in range(2):\n",
    "\tprint(\"interation {} start\".format(iteration))\n",
    "\tos.system(\"sudo dfs 0 {}\".format(f))\n",
    "\tdma.sendchannel.start()\n",
    "\tdma.recvchannel.start()\n",
    "\ttotal_time = 0\n",
    "\tTDM_list = []\n",
    "\tfor i in range(repeat):\n",
    "\t\tfor b in range(len(image_batchs)):\n",
    "\t\t\tnp.copyto(img[ping], image_list[b])\n",
    "\t\t\tstart = time.time()\n",
    "\t\t\tdma.sendchannel.transfer(img[ping])\n",
    "\t\t\tdma.recvchannel.transfer(out[ping])\n",
    "\t\t\tphase_shift(PulseGen)\n",
    "\t\t\tstatus = TDM.read(0x00)\n",
    "\t\t\tTDM_list.append(status)\n",
    "\t\t\tdma.recvchannel.wait()\n",
    "\t\t\tdma.sendchannel.wait()\n",
    "\t\t\tend = time.time()\n",
    "\t\t\ttotal_time += end - start\n",
    "\t\t\tcboxer.compute(out[ping], result[b])\n",
    "\tprint(\"interation {} finish\".format(iteration))\n",
    "\titeration += 1\n",
    "\n",
    "\tresult = result.reshape(-1, 4)\n",
    "\tfps = repeat*len(result)/total_time\n",
    "\tIoU = calculate_aiou(ground_truth_box, result)\n",
    "\n",
    "\tTDM_values = np.array(TDM_list).reshape(MMF_V, T)\n",
    "\tpath_mmf_v = mff_v(TDM_values, cpi, T)\n",
    "\tpath_mmf_v = mff_h(path_mmf_v, MMF_H)\n",
    "\ttheta1, theta2 = find_theta(path_mmf_v)\n",
    "\ttheta = calculate_theta(theta1, theta2, T)\n",
    "\ttheta_ref = int(t_ref[cpi]/1000*f*T)\n",
    "\ttheta += round((theta_ref - theta)/T)*T\n",
    "\tt_shadow = theta/T*1000/f\n",
    "\tt_d = t_shadow - t_skew[cpi]*uv[vi]\n",
    "\t# t_d = t_shadow\n",
    "\tFPGA_temperature = get_FPGA_temperature()\n",
    "\n",
    "\tprint(\"Frequency {}MHz, theta {}, t_shadow {:.3f}ns, t_d {:.3f}ns, FPGA temperature {:.3f}°C\".format(f, theta, t_shadow, t_d, FPGA_temperature))\n",
    "\tlog = open(\"AOS-{}mV-path{}.log\".format(vs[vi], cpi), \"a+\")\n",
    "\tlog.write(\"{}\\t{}\\t{:.3f}\\t{:.3f}\\t{:.3f}\\n\".format(f, theta, t_shadow, t_d, FPGA_temperature))\n",
    "\tlog.close()\n",
    "\n",
    "\tif(1000/t_d > f + 10):\n",
    "\t\tf += 10\n",
    "\telif(1000/t_d > f):\n",
    "\t\tf += 1\n",
    "\telif(1000/t_d < f - 10):\n",
    "\t\tf -= 10\n",
    "\telse:\n",
    "\t\tf -= 1"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
